import os, logging
from flask import Flask,g
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
from config import config
from datetime import datetime, date
from json import JSONEncoder
from logging.handlers import RotatingFileHandler
from .utils import RedisUtil

class CustomJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        else:
            return JSONEncoder.default(self, obj)

# 创建一个日志格式，包含请求ID
class ContextFilter(logging.Filter):
    def filter(self, record):
        record.trace_id = getattr(g, 'trace_id', '')
        return True

# 获取当前绝对路径
def get_cwd():
    return os.path.dirname(os.path.abspath(__file__))

moment = Moment()
db = SQLAlchemy()
redis_client = None

def create_app(config_name):
    
    app = Flask(__name__)

    #  替换默认的json编码器
    app.json_encoder = CustomJSONEncoder

    # 关闭json中文编码
    # 此方式高版本可用，低版本使用app.config["JSON_AS_ASCII"] = False
    app.json.ensure_ascii = False

    # 加载配置
    app.config.from_object(config[config_name])

    # 日期格式化
    moment.init_app(app)
    # 数据库初始化
    db.init_app(app)

    # redis客户端初始化
    global redis_client
    redis_client = RedisUtil.from_url(url=app.config["REDIS_URL"], 
                                      max_connections=app.config["REDIS_MAX_CONNECTIONS"],
                                      socket_timeout=app.config["REDIS_TIMEOUT"],
                                      socket_connect_timeout=app.config["REDIS_CONNECTION_TIMEOUT"])
   
    # 注册蓝图
    from .base import base as base_blueprint
    app.register_blueprint(base_blueprint)

    # 滚动文件日志
    handler = RotatingFileHandler(config[config_name].LOG_FILENAME or 'flaskapp.log', encoding='UTF-8', maxBytes=1024*1024*100, backupCount=100)
    # 日志过滤器添加trace_id
    handler.addFilter(ContextFilter())
    # 日志格式
    formatter = logging.Formatter('%(asctime)s -[%(levelname)s][%(trace_id)s][%(filename)s - %(funcName)s - %(lineno)s]: %(message)s')
    handler.setFormatter(formatter)
    # 日志级别
    handler.setLevel(config[config_name].LOG_LEVEL or logging.INFO)
    # 启用日志配置
    app.logger.addHandler(handler)
    
    return app
